#include <stdint.h>
#include "hypercalls.h"

/*
  minimal MetaROUTER app example - console driver

  Copyright (C) 2013 Peter Lawrence

  All rights reserved.

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU Lesser General Public License version 2.1, as
  published by the Free Software Foundation.  This program is
  distributed in the hope that it will be useful, but WITHOUT ANY
  WARRANTY; without even the implied warranty of MERCHANTABILITY or
  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
  License for more details.

  You should have received a copy of the GNU Lesser General Public License
  along with this program; if not, see <http://www.gnu.org/licenses/>.
*/

/* temporary value of debugging interest that will be displayed via console */
extern uint32_t veth_iftrack;

#define CONS_BUF_SIZE	4096

static volatile struct vdma_descr cons_tx_descr;
static volatile struct vdma_descr cons_rx_descr;

static uint8_t cons_rx_buffer[CONS_BUF_SIZE], cons_tx_buffer[CONS_BUF_SIZE];

const uint8_t hexdigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };

void hexprint(uint8_t *data, int length)
{
	static unsigned t;

	/*
	if the VDMA_DONE bit has been cleared by the host, we can reset the write pointer
	if not, we keep the existing value of t (effectively appending new data to existing data)
	*/
	if (~(cons_tx_descr.size & VDMA_DONE))
		t = 0;

	/* loop only whilst writing within the buffer limits */
	while ((t + 2) < CONS_BUF_SIZE)
	{
		if (length)
		{
			/* data left to write */
			cons_tx_buffer[t++] = hexdigits[*data >> 4];
			cons_tx_buffer[t++] = hexdigits[*data & 0xF];
			*data++;
			length--;
		}
		else
		{
			/* terminate the text we wrote with a line-ending and exit the loop */
			cons_tx_buffer[t++] = 13; /* CR */
			cons_tx_buffer[t++] = 10; /* LF */
			break;
		}
	}

	/* indicate to the host that data has been written (VDMA_DONE set) and indicate how much (value of t) */
	cons_tx_descr.size = VDMA_DONE | t;
}

void vm_init_console(void)
{
	/* the MetaROUTER virtual console consists of two buffers, one each for transmit and receive */

	cons_rx_descr.addr = (unsigned) cons_rx_buffer;
	cons_rx_descr.size = CONS_BUF_SIZE;
	cons_rx_descr.next = (unsigned) &cons_rx_descr;
	
	cons_tx_descr.addr = (unsigned) cons_tx_buffer;
	cons_tx_descr.size = 0;
	cons_tx_descr.next = (unsigned) &cons_tx_descr;

	/* inform the host as to the location of the data structures that point to the buffers */
	vm_create_queue(1, 1, (unsigned) &cons_tx_descr, (unsigned) &cons_rx_descr);
}

void vm_service_console(void)
{
	unsigned count;

	count = cons_rx_descr.size;

	/* check if the user has entered any keystrokes... */
	if (count & VDMA_DONE)
	{
		/* ... yes, the user has typed something */

		/* print debugging item of interest in response to keystroke */
		hexprint((uint8_t *)&veth_iftrack, 4);

		/* update the data structure to tell the host all keystrokes have been received */ 
		cons_rx_descr.size = CONS_BUF_SIZE;
	}
}

